<template>
  <div class="json-to-excel-container">
    <div class="header">
      <h1>JSON转Excel工具</h1>
      <p>轻松将JSON数据转换为Excel文件进行下载</p>
    </div>

    <div class="app-card">
      <div class="app-body">
        <!-- 输入区域 -->
        <div class="input-section">
          <div class="section-title">
            <svg
              width="20"
              height="20"
              viewBox="0 0 24 24"
              fill="none"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                d="M14 2H6C5.46957 2 4.96086 2.21071 4.58579 2.58579C4.21071 2.96086 4 3.46957 4 4V20C4 20.5304 4.21071 21.0391 4.58579 21.4142C4.96086 21.7893 5.46957 22 6 22H18C18.5304 22 19.0391 21.7893 19.4142 21.4142C19.7893 21.0391 20 20.5304 20 20V8L14 2Z"
                stroke="#3498db"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <path
                d="M14 2V8H20"
                stroke="#3498db"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <path
                d="M16 13H8"
                stroke="#3498db"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <path
                d="M16 17H8"
                stroke="#3498db"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <path
                d="M10 9H9H8"
                stroke="#3498db"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
            </svg>
            <span>JSON输入</span>
          </div>

          <textarea
            v-model="jsonInput"
            class="json-input"
            placeholder='请输入有效的JSON数据，例如：
[
  {"姓名": "张三", "年龄": 28, "城市": "北京", "职业": "工程师"},
  {"姓名": "李四", "年龄": 32, "城市": "上海", "职业": "设计师"},
  {"姓名": "王五", "年龄": 25, "城市": "广州", "职业": "产品经理"}
]'
          ></textarea>

          <div class="controls">
            <button @click="clearInput" class="btn btn-secondary">清空</button>
            <button @click="loadSampleData" class="btn btn-secondary">示例数据</button>
            <button @click="processJson" class="btn btn-primary">解析JSON</button>
          </div>

          <div v-if="errorMessage" class="error-message">
            <svg
              width="16"
              height="16"
              viewBox="0 0 24 24"
              fill="none"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                d="M12 8V12M12 16H12.01M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z"
                stroke="#e74c3c"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
            </svg>
            {{ errorMessage }}
          </div>
        </div>

        <!-- 预览区域 -->
        <div class="preview-section">
          <div class="section-title">
            <svg
              width="20"
              height="20"
              viewBox="0 0 24 24"
              fill="none"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                d="M9 17H15M9 13H15M9 9H10M5 21H19C20.1046 21 21 20.1046 21 19V5C21 3.89543 20.1046 3 19 3H5C3.89543 3 3 3.89543 3 5V19C3 20.1046 3.89543 21 5 21Z"
                stroke="#3498db"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
            </svg>
            <span>数据预览</span>
            <span class="row-count" v-if="tableData.length > 0">({{ tableData.length }} 行)</span>
          </div>

          <div class="preview-container" v-if="tableData.length > 0">
            <div class="table-container">
              <table class="preview-table">
                <thead>
                  <tr>
                    <th v-for="(header, index) in tableHeaders" :key="index">
                      {{ header }}
                    </th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="(row, rowIndex) in tableData" :key="rowIndex">
                    <td v-for="(header, colIndex) in tableHeaders" :key="colIndex">
                      {{ row[header] }}
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>

            <div class="export-controls">
              <div class="filename-input">
                <label for="filename">文件名:</label>
                <input id="filename" type="text" v-model="fileName" placeholder="输入文件名" />
                <span>.xlsx</span>
              </div>
              <button @click="exportToExcel" class="btn btn-success">
                <svg
                  width="16"
                  height="16"
                  viewBox="0 0 24 24"
                  fill="none"
                  xmlns="http://www.w3.org/2000/svg"
                >
                  <path
                    d="M21 15V19C21 19.5304 20.7893 20.0391 20.4142 20.4142C20.0391 20.7893 19.5304 21 19 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V15"
                    stroke="white"
                    stroke-width="2"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                  />
                  <path
                    d="M7 10L12 15L17 10"
                    stroke="white"
                    stroke-width="2"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                  />
                  <path
                    d="M12 15V3"
                    stroke="white"
                    stroke-width="2"
                    stroke-linecap="round"
                    stroke-linejoin="round"
                  />
                </svg>
                导出Excel
              </button>
            </div>
          </div>

          <div v-else class="empty-state">
            <svg
              width="64"
              height="64"
              viewBox="0 0 24 24"
              fill="none"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                d="M14 2H6C5.46957 2 4.96086 2.21071 4.58579 2.58579C4.21071 2.96086 4 3.46957 4 4V20C4 20.5304 4.21071 21.0391 4.58579 21.4142C4.96086 21.7893 5.46957 22 6 22H18C18.5304 22 19.0391 21.7893 19.4142 21.4142C19.7893 21.0391 20 20.5304 20 20V8L14 2Z"
                stroke="#bdc3c7"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <path
                d="M14 2V8H20"
                stroke="#bdc3c7"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <path
                d="M16 13H8"
                stroke="#bdc3c7"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <path
                d="M16 17H8"
                stroke="#bdc3c7"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
              <path
                d="M10 9H9H8"
                stroke="#bdc3c7"
                stroke-width="2"
                stroke-linecap="round"
                stroke-linejoin="round"
              />
            </svg>
            <p>解析后的数据将在这里显示</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, computed } from 'vue'

export default {
  name: 'JsonToExcel',
  setup () {
    const jsonInput = ref('')
    const tableData = ref([])
    const errorMessage = ref('')
    const fileName = ref('json_data')

    // 计算表格头部
    const tableHeaders = computed(() => {
      if (tableData.value.length === 0) return []

      const headers = new Set()
      tableData.value.forEach(row => {
        Object.keys(row).forEach(key => headers.add(key))
      })

      return Array.from(headers)
    })

    // 处理JSON数据
    const processJson = () => {
      errorMessage.value = ''

      if (!jsonInput.value.trim()) {
        errorMessage.value = '请输入JSON数据'
        return
      }

      try {
        const parsedData = JSON.parse(jsonInput.value)

        // 验证数据格式
        if (!Array.isArray(parsedData)) {
          errorMessage.value = 'JSON数据必须是一个数组'
          return
        }

        if (parsedData.length === 0) {
          errorMessage.value = 'JSON数组不能为空'
          return
        }

        tableData.value = parsedData
      } catch (error) {
        errorMessage.value = 'JSON格式错误: ' + error.message
      }
    }

    // 清空输入
    const clearInput = () => {
      jsonInput.value = ''
      tableData.value = []
      errorMessage.value = ''
    }

    // 加载示例数据
    const loadSampleData = () => {
      jsonInput.value = `[
  {
    "姓名": "张三",
    "年龄": 28,
    "城市": "北京",
    "职业": "工程师",
    "入职日期": "2020-03-15",
    "薪资": 15000
  },
  {
    "姓名": "李四",
    "年龄": 32,
    "城市": "上海",
    "职业": "设计师",
    "入职日期": "2019-07-22",
    "薪资": 12000
  },
  {
    "姓名": "王五",
    "年龄": 25,
    "城市": "广州",
    "职业": "产品经理",
    "入职日期": "2021-01-10",
    "薪资": 14000
  },
  {
    "姓名": "赵六",
    "年龄": 29,
    "城市": "深圳",
    "职业": "前端开发",
    "入职日期": "2020-11-05",
    "薪资": 16000
  },
  {
    "姓名": "钱七",
    "年龄": 35,
    "城市": "杭州",
    "职业": "后端开发",
    "入职日期": "2018-05-30",
    "薪资": 18000
  }
]`
    }

    // 导出为Excel
    const exportToExcel = () => {
      if (tableData.value.length === 0) {
        errorMessage.value = '没有数据可导出'
        return
      }

      try {
        // 动态导入xlsx库
        import('xlsx').then(xlsx => {
          // 创建工作簿
          const wb = xlsx.utils.book_new()

          // 将数据转换为工作表
          const ws = xlsx.utils.json_to_sheet(tableData.value)

          // 将工作表添加到工作簿
          xlsx.utils.book_append_sheet(wb, ws, 'Sheet1')

          // 生成Excel文件并下载
          xlsx.writeFile(wb, `${fileName.value || 'json_data'}.xlsx`)
        }).catch(error => {
          errorMessage.value = '导出失败: ' + error.message
        })
      } catch (error) {
        errorMessage.value = '导出失败: ' + error.message
      }
    }

    return {
      jsonInput,
      tableData,
      errorMessage,
      fileName,
      tableHeaders,
      processJson,
      clearInput,
      loadSampleData,
      exportToExcel
    }
  }
}
</script>

<style scoped>
.json-to-excel-container {
  min-height: 100vh;
  background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
  color: #333;
  padding: 20px;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.header {
  text-align: center;
  margin-bottom: 30px;
  color: white;
}

.header h1 {
  font-size: 1rem;
  margin-bottom: 10px;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
}

.header p {
  font-size: 0.5rem;
  opacity: 0.9;
}

.app-card {
  background: white;
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
  overflow: hidden;
  max-width: 1400px;
  margin: 0 auto;
}

.app-body {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 30px;
}

@media (min-width: 768px) {
}

.input-section,
.preview-section {
  flex: 1;
}

.section-title {
  font-size: 0.5rem;
  margin-bottom: 15px;
  color: #2c3e50;
  display: flex;
  align-items: center;
  gap: 10px;
}

.row-count {
  font-size: 0.5rem;
  color: #7f8c8d;
  font-weight: normal;
}

.json-input {
  width: 100%;
  height: 300px;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 8px;
  font-family: 'Courier New', monospace;
  font-size: 16 px;
  resize: vertical;
  transition: border-color 0.3s;
}

.json-input:focus {
  outline: none;
  border-color: #3498db;
  box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
}

.controls {
  display: flex;
  gap: 10px;
  margin-top: 15px;
  flex-wrap: wrap;
}

.btn {
  padding: 10px 16px;
  border: none;
  border-radius: 6px;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  transition: all 0.3s;
}

.btn-primary {
  background-color: #3498db;
  color: white;
}

.btn-primary:hover {
  background-color: #2980b9;
  transform: translateY(-2px);
}

.btn-secondary {
  background-color: #ecf0f1;
  color: #2c3e50;
}

.btn-secondary:hover {
  background-color: #bdc3c7;
}

.btn-success {
  background-color: #2ecc71;
  color: white;
}

.btn-success:hover {
  background-color: #27ae60;
  transform: translateY(-2px);
}

.error-message {
  color: #e74c3c;
  margin-top: 10px;
  padding: 10px;
  background-color: #ffeaea;
  border-radius: 5px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.preview-container {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.table-container {
  overflow: auto;
  max-height: 400px;
  border: 1px solid #ddd;
  border-radius: 8px;
  margin-bottom: 20px;
}

.preview-table {
  width: 100%;
  border-collapse: collapse;
}

.preview-table th {
  background-color: #f8f9fa;
  padding: 12px 15px;
  text-align: left;
  font-weight: 600;
  border-bottom: 2px solid #dee2e6;
  position: sticky;
  top: 0;
}

.preview-table td {
  padding: 10px 15px;
  border-bottom: 1px solid #dee2e6;
}

.preview-table tr:hover {
  background-color: #f8f9fa;
}

.export-controls {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 15px;
  flex-wrap: wrap;
}

.filename-input {
  display: flex;
  align-items: center;
  gap: 8px;
}

.filename-input label {
  font-weight: 600;
  white-space: nowrap;
}

.filename-input input {
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  width: 150px;
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 300px;
  color: #7f8c8d;
  text-align: center;
}

.empty-state p {
  margin-top: 15px;
  font-size: 0.5rem;
}

@media (max-width: 768px) {
  .header h1 {
    font-size: 1rem;
  }

  .app-body {
    padding: 20px;
  }

  .export-controls {
    flex-direction: column;
    align-items: stretch;
  }

  .filename-input {
    justify-content: space-between;
  }
}
</style>